package excelBase;

import java.util.ArrayList;

import lib.CellInLib;
import lib.MergeInLib;
import lib.RowInLib;
import lib.SheetInLib;
import main.ErrorException;
import main.WarningHandler;
import xml.XmlDoc;
import xml.XmlNode;
import code.ReferenceClass;
import define.Common;
import define.Config;
import define.ErrorDefine;
import define.ExcelType;
import define.WarningDefine;

public class Sheet extends BaseContent
{
	private ArrayList<Head> m_heads;

	private SheetInLib m_sheet;
	private int m_firstRow;
	private ExcelType m_type;
	private ExcelFile m_excel;
	private ReferenceClass m_referenceClass;
	
	public Sheet(SheetInLib sheet, ExcelType type, ExcelFile excel) throws ErrorException
	{
		super(sheet.getName());
		m_children = new ArrayList<>();
		m_sheet = sheet;
		m_heads = new ArrayList<Head>();
		m_type = type;
		m_excel = excel;
	}
	
	public void init() throws ErrorException
	{
		switch(m_type) 
		{
		case E_TABLE_EXT:
			makeTableChild();
			break;
		case E_TREE_EXT:
			makeTreeChild();
			break;
		case E_REFERENCE_EXT:
		{
			makeTableChild();
			makeReference();
		}
			break;
		default:
			break;
		}
	}
	
	private void makeTableChild()
	{
		makeHead();
		if(m_heads.size() == 0)
		{
			return;
		}
		makeRowContent();
	}
	
	private void makeReference() throws ErrorException
	{
		m_referenceClass = new ReferenceClass(this);
	}
	
	private void makeTreeChild() throws ErrorException
	{
		RowInLib firstRow = null;
		int len = m_sheet.getRowNumber();
		for(int i = 0; i < len; ++i)
		{
			firstRow = m_sheet.getRow(i);
			if(!firstRow.isEmpty())
			{
				m_firstRow = i;
				break;
			}
		}
		if(firstRow == null || firstRow.isEmpty())
		{
			new WarningHandler(WarningDefine.E_EMPTY_SHEET_WARNING, m_sheet.getName()).showWarning();
			return;
		}
		len = firstRow.getCellNumber();
		int cellIndex = -1;
		for(int i = 0; i < len; ++i)
		{
			CellInLib cell = firstRow.getCell(i);
			if(!cell.IsEmpty())
			{
				cellIndex = i;
				break;
			}
		}
		MergeInLib merge = m_sheet.isMergeCell(m_firstRow, cellIndex);
		if(merge == null)
		{
			merge = new MergeInLib(m_firstRow, cellIndex);
		}
		m_children.add(new Node(merge, this, m_firstRow + merge.getHeight() < m_sheet.getRowNumber()));
	}
	
	private void makeHead()
	{
	
		RowInLib firstRow = null;
		int len = m_sheet.getRowNumber();
		for(int i = 0; i < len; ++i)
		{
			firstRow = m_sheet.getRow(i);
			if(!firstRow.isEmpty())
			{
				m_firstRow = i;
				break;
			}
		}
		if(firstRow == null || firstRow.isEmpty())
		{
			new WarningHandler(WarningDefine.E_EMPTY_SHEET_WARNING, m_sheet.getName()).showWarning();
			return;
		}
		len = firstRow.getCellNumber();
		for(int i = 0; i < len; ++i)
		{
			CellInLib cell = firstRow.getCell(i);
			if(!cell.IsEmpty())
			{
				Head head = new Head(firstRow, i);
				MergeInLib merge = m_sheet.isMergeCell(m_firstRow, i);
				if(merge != null)
				{
					i = merge.getX2();
				}
				head.setEnd(i);
				if(hasHead(head.getName()) != null)
				{
					new WarningHandler(WarningDefine.E_SHEET_ALREAD_HAS_HEAD_WARNING, head.getName()).showWarning();
				}
				m_heads.add(head);
			}
		}
	}

	private void makeRowContent()
	{
		int len = m_sheet.getRowNumber();
		for(int i = m_firstRow + 1; i < len; ++i)
		{
			RowInLib row = m_sheet.getRow(i);
			if(!row.isEmpty())
			{
				RowContent content = new RowContent(m_sheet, i);
				MergeInLib merge = m_sheet.isMergeCell(i, 0);
				if(merge != null)
				{
					i = merge.getY2();
				}
				content.setEnd(i);
				content.makeMember(m_heads);
				m_children.add(content);
			}
		}
	}
	
	public Head getHead(int index) throws ErrorException
	{
		if(index < 0 || index >= m_heads.size())
		{
			throw new ErrorException(ErrorDefine.E_HEAD_NUMBER_ERROR, m_name, Config.NO_POSITION);
		}
		return m_heads.get(index);
	}
	
	public Head hasHead(String name)
	{
		for(Head temp: m_heads)
		{
			if(name.compareTo(temp.getName()) == 0)
			{
				return temp;
			}
		}
		return null;
	}
	
	public ReferenceClass getReferenceClass()
	{
		return m_referenceClass;
	}
	
	public int getRowNumber()
	{
		return m_children.size();
	}
	
	public int getRowMemberNumber()
	{
		return m_heads.size();
	}
	
	public int getFirstRow()
	{
		return m_firstRow;
	}
	
	public Head hasExcelTypeHead(ExcelType type)
	{
		for(Head temp: m_heads)
		{
			if(temp.getName().compareTo(type.getName()) == 0)
			{
				return temp;
			}
		}
		return null;
	}
	
	public ArrayList<String> getContentOfHead(Head head) throws ErrorException
	{
		ArrayList<String> list = new ArrayList<>();
		for(BaseContent base: m_children)
		{
			String value = base.getChild(head.getName(), Config.NO_POSITION).getChild(0, Config.NO_POSITION).getName();
			if(value.length() != 0)
			{
				list.add(value);
			}
		}
		return list;
	}
	
	public String getCellValue(int row, int column)
	{
		return m_sheet.getCellValue(row, column);
	}
	
	public short getCellBgColor(int row, int column)
	{
		return m_sheet.getBackgroundColor(row, column);
	}
	
	public short getCellFgColor(int row, int column)
	{
		return m_sheet.getForegroundColor(row, column);
	}
	
	public short getNotAttributeBgColor()
	{
		return m_excel.getNotAttributeBGColor();
	}
	
	public short getNotAttributeFgColor()
	{
		return m_excel.getNotAttributeFGColor();
	}
	
	public CellInLib getCell(int row, int column)
	{
		return m_sheet.getCellInLib(row, column);
	}
	
	public MergeInLib isMergeCell(int row, int column)
	{
		return m_sheet.isMergeCell(row, column);
	}
	
	public RowInLib getRow(int index)
	{
		return m_sheet.getRow(index);
	}
	
	public XmlDoc getXmlDoc(int position) throws ErrorException
	{
		if(m_type != ExcelType.E_TREE_EXT)
		{
			throw new ErrorException(ErrorDefine.E_SHEET_TYPE_WRONG, m_name, position);
		}
		try 
		{
			XmlNode root = ((Node)m_children.get(0)).getXmlNode();
			return new XmlDoc(root);
		}
		catch(Exception e) 
		{
			throw new ErrorException(ErrorDefine.E_XML_ERROR, e.getMessage(), Config.NO_POSITION);
		}
	}
	
	public ExcelType getExcelType()
	{
		return m_type;
	}
	
	public String[] getCodeText(String text) throws ErrorException
	{
		String[] texts = new String[m_children.size()];
		for(int i = 0, max = m_children.size(); i < max; ++i)
		{
			BaseContent base = m_children.get(i);
			texts[i] = base.getChild(text, Config.NO_POSITION).getChild(0, Config.NO_POSITION).getName();
			texts[i] = Common.removeBlank(texts[i]);
		}
		return texts;
	}
}


